﻿using System.Linq;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Discounts;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Shipping;
using Nop.Core.Domain.Tax;
using Nop.Services.Catalog;
using Nop.Services.Discounts;
using Nop.Services.Orders;
using Nop.Services.Payments;
using Nop.Services.Shipping;
using Nop.Services.Tax;

namespace Nop.Plugin.Pricing.PreciousMetals.Services
{
    public class PreciousMetalsOrderTotalCalculationService : OrderTotalCalculationService
    {
        private readonly IPriceCalculationService _priceCalculationService;
        private readonly IPreciousMetalsDetailService _preciousMetalsDetailService;
        private readonly PreciousMetalsSettings _preciousMetalsSettings;

        #region Constructor
        public PreciousMetalsOrderTotalCalculationService(
            IWorkContext workContext, IPriceCalculationService priceCalculationService, ITaxService taxService, IShippingService shippingService,
            IPaymentService paymentService, ICheckoutAttributeParser checkoutAttributeParser, IDiscountService discountService,
            IGiftCardService giftCardService, TaxSettings taxSettings, RewardPointsSettings rewardPointsSettings, ShippingSettings shippingSettings,
            ShoppingCartSettings shoppingCartSettings, CatalogSettings catalogSettings, IPreciousMetalsDetailService preciousMetalsDetailService,
            PreciousMetalsSettings preciousMetalsSettings)
            : base(workContext, priceCalculationService, taxService, shippingService, paymentService, checkoutAttributeParser, discountService,
            giftCardService, taxSettings, rewardPointsSettings, shippingSettings, shoppingCartSettings, catalogSettings)
        {
            _priceCalculationService = priceCalculationService;
            _preciousMetalsDetailService = preciousMetalsDetailService;
            _preciousMetalsSettings = preciousMetalsSettings;
        }

        #endregion

        public override decimal GetOrderSubtotalDiscount(Customer customer, decimal orderSubTotal, out Discount appliedDiscount)
        {
            if (_preciousMetalsSettings.ExcludeFromSubtotalDiscounts)
            {
                // get the subtotal of precious metals items
                var pmSubtotal = 0m;
                var shoppingCartItems = customer.ShoppingCartItems.Where(x => x.ShoppingCartType == ShoppingCartType.ShoppingCart);
                foreach (var shoppingCartItem in shoppingCartItems)
                {
                    var detail = _preciousMetalsDetailService.Get(shoppingCartItem.ProductVariantId);
                    if (detail == null)
                        continue;

                    var price = this._priceCalculationService.GetSubTotal(shoppingCartItem, true);
                    pmSubtotal += price;
                }

                // exclude precious metals pricing from the subtotal
                orderSubTotal -= pmSubtotal;
            }

            return base.GetOrderSubtotalDiscount(customer, orderSubTotal, out appliedDiscount);
        }
    }
}
